﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace CommonUtils
{
    /// <summary>
    /// 路径处理
    /// </summary>
    public static class PathUtil
    {
        public const string LogPath = "console.log";

        /// <summary>
        /// 基础路径 带/
        /// </summary>
        public static string AppBase { get; }

        /// <summary>
        /// 项目路径 仅用于开发环境 带/
        /// </summary>
        public static string ProjectRoot { get; }

        /// <summary>
        /// 初始化
        /// </summary>
        static PathUtil()
        {
            AppBase = AppDomain.CurrentDomain.BaseDirectory.ReplaceSpritLeft2Right();
            ProjectRoot = AppBase.SubstringStartByFirst("/bin/") + '/';
        }

        /// <summary>
        /// 全路径
        /// </summary>
        public static string GetFull(params string[] partPaths)
        => AppBase.Combine(partPaths);

        /// <summary>
        /// 不带/
        /// </summary>
        public static string GetTempFolder()
        => GetFull("temp");

        public static string GetTemp(string extension)
        => GetFull(GetTempFolder() + "/" + StringUtil.GetGuid(extension));

        /// <summary>
        /// 项目路径 仅用于开发环境
        /// </summary>
        public static string GetProjectFull(params string[] partPaths)
        => ProjectRoot.Combine(partPaths);

        /// <summary>
        /// 通过磁盘路径，获取虚拟路径
        /// </summary>
        public static string GetVirtual(string fullPath)
        {
            string rootPath = AppBase.Replace('\\', '/');
            fullPath = fullPath.Replace('\\', '/');
            return "/" + fullPath.Replace(rootPath, "");
        }

        /// <summary>
        /// 路径合并 支持上级目录.. \→/
        /// </summary>
        public static string Combine(this string left, params object[] rights)
        {
            //统一字符
            var path = new StringBuilder(left.Replace('\\', '/'));
            foreach (var value in rights)
            {
                //有些方法默认参数为null会传过来 
                if (value == null)
                    continue;

                //统一字符
                var right = value.ToString().Replace('\\', '/');
                // ../../处理 System.IO.Path.Combine(paths)如果right是/开头，那么left就会丢失，../也不会处理
                int up = right.CountOf("../");
                right = right.Remove("../", "./");
                //寻找上级
                if (up > 0)
                {
                    var tempLeft = path.ToString().ReplaceRecursive("//", "/");
                    if (tempLeft[tempLeft.Length - 1] == '/')
                        tempLeft = tempLeft.Substring(0, tempLeft.Length - 1);
                    while (up-- > 0)
                        tempLeft = tempLeft.Substring(0, tempLeft.LastIndexOf('/'));
                    path = new StringBuilder(tempLeft);
                }

                //忽略空 因为right有改变，所以这里再判断一遍
                if (string.IsNullOrEmpty(right))
                    continue;

                //判断是否有隔离符
                var leftHas = path.Length > 0 && path[path.Length - 1] == '/';
                var rightHas = right[0] == '/';

                //都有
                if (leftHas && rightHas)
                {
                    path.Append(right.Substring(1));
                    continue;
                }

                //一个有
                if (leftHas || rightHas)
                {
                    path.Append(right);
                    continue;
                }

                //都没有
                if (!leftHas && !rightHas)
                {
                    path.Append('/');
                    path.Append(right);
                }
            }
            return path.ToString();
        }

        /// <summary>
        /// 后缀前名字后附加
        /// </summary>
        public static string NameAppend(string path, string append)
        {
            var index = path.LastIndexOf('.');
            if (index < 0)
                return path + append;
            return path.Substring(0, index) + append + path.Substring(index);
        }

        /// <summary>
        /// 更改后缀名
        /// </summary>
        public static string ChangeExtension(string path, string extension)
        {
            var index = path.LastIndexOf('.');
            if (index < 0)
                return path + extension;
            return path.Substring(0, index) + extension;
        }

        /// <summary>
        /// 替换后缀名
        /// </summary>
        public static string ReplaceExtention(string path, string extension)
        => ChangeExtension(path, extension);

        /// <summary>
        /// 枚举路径源
        /// </summary>
        public static string EnumSources()
        {
            var list = new List<StringStringPair>();

            list.Add("Environment.SystemDirectory", Environment.SystemDirectory);//C:\Windows\system32
            list.Add("Environment.CurrentDirectory", Environment.CurrentDirectory);//[ProjectDirectory]
            list.Add("AppDomain.CurrentDomain.BaseDirectory", AppDomain.CurrentDomain.BaseDirectory);//[ApplicationDirectory]
            list.Add("Process.GetCurrentProcess().MainModule.FileName", Process.GetCurrentProcess().MainModule.FileName);//C:\Program Files\IIS Express\iisexpress.exe
            list.Add("Directory.GetCurrentDirectory()", Directory.GetCurrentDirectory());//[ProjectDirectory]

            list.Add("new FileInfo(\"/\").FullName", new FileInfo("/").FullName);//[DiskRoot]
            list.Add("new FileInfo(\"./\").FullName", new FileInfo("./").FullName);//[ProjectDirectory]
            list.Add("new DirectoryInfo(\"/\").FullName", new DirectoryInfo("/").FullName);//[DiskRoot]
            list.Add("new DirectoryInfo(\"./\").FullName", new DirectoryInfo("./").FullName);//[ProjectDirectory]

            list.Add("AppBase", AppBase);
            list.Add("ProjectRoot", ProjectRoot);

            var sb = new StringBuilder();
            foreach (var item in list)
                sb.AppendLine("({0})=[{1}] ", item.Key, item.Value);
            return sb.ToString();
        }
    }
}
